/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-9-20   22:29
* filename: LaborD3D10FileTexture.cpp
-----------------------------------------------------------------------------
*/

#include "LaborD3D10FileTexture.h"
#include "Common/LaborCommonFunction.h"
#include "LaborD3D10RenderSystem.h"
NAMESPACE_LABOR3D_BEGIN


const int NBYTE_ALAIGN = 4;

eLPIXEL_FORMAT  CLD3D10FileTexture::getFormat()
{
	return eL_PF_R32G32B32A32F;
}


CLD3D10FileTexture::~CLD3D10FileTexture()
{
	unload();
	//m_pRenderer->removeCreatedTexture(this);
}


CLD3D10FileTexture::CLD3D10FileTexture(CLD3D10RenderSystem* pDevice) : CLD3D10BasicTexture(pDevice)
{
	//m_pImage = NULL;
	m_pRenderer           = pDevice;
	m_pShaderResourceView = NULL;
	m_Filter              = eL_FILTER_MIN_MAG_MIP_POINT;
	m_pFileBuffer         = NULL;
	m_Width               = 0;
	m_Height              = 0;
	m_bLoadingFinish      = true;
	//m_pRenderer->initVideoCtrlParam(m_VideoCtrlParam);
	//m_pRenderer->addACreatedTexture((CXUITexture*)this);
	m_bFlipY              = false;


	m_p1DTex   = NULL;
	m_p2DTex   = NULL;
	m_p3DTex   = NULL;	
	m_pTexture = NULL;	

	ZeroMemory( &m_srvDesc, sizeof(D3D10_SHADER_RESOURCE_VIEW_DESC) );
}

bool CLD3D10FileTexture::getImageSize(int& w , int& h)
{
	w  = m_Width  ;
	h  = m_Height ;
	return true;
}

bool  CLD3D10FileTexture::getPixel(int x , int y , CLColor_4f& _cl)
{
	//if(m_pImage == NULL) return false;
	//CX2DImage::ImageSize _size =  m_pImage->getImageSize();

	//if(isFlipY())
	//{
	//	y = _size.m_Height - y;
	//}

	////	y = _size.m_Height - y;

	//if(m_pImage->getBytePerPixel( ) == 3)
	//{
	//	CXColor_4ub* pColor =  (CXColor_4ub*)(m_pImage->getImageData() + 3 * (x + y * _size.m_Width ) ) ;
	//	_cl.r = pColor->r / 255.0f;
	//	_cl.g = pColor->g / 255.0f;
	//	_cl.b = pColor->b / 255.0f;
	//	_cl.a = 1.0f;
	//}
	//else if(m_pImage->getBytePerPixel( ) == 4)
	//{
	//	CXColor_4ub* pColor =  (CXColor_4ub*)(m_pImage->getImageData() + 4 * (x + y * _size.m_Width ) ) ;
	//	_cl.r = pColor->r / 255.0f;
	//	_cl.g = pColor->g / 255.0f;
	//	_cl.b = pColor->b / 255.0f;
	//	_cl.a = pColor->a / 255.0f;
	//}
	//else
	//{
	//	return false;
	//}
	return true;
}

void  CLD3D10FileTexture::getUVRange(float& minx , float& miny , float& maxx , float& maxy)
{
	minx = 0.0f;
	miny = 0.0f;
	maxx = 1.0f;
	maxy = 1.0f;
}

bool  CLD3D10FileTexture::getDim(sTexSize_t& size)
{
	if( m_pShaderResourceView == NULL )
	{
		size.m_Width  = 0;
		size.m_Height = 0;
		size.m_BytePerPixel = 4;
		return false;
	}
	size.m_Width        = m_Width;
	size.m_Height       = m_Height;
	size.m_BytePerPixel = 4;
	return true;
}

void* CLD3D10FileTexture::lock( SURF_LOCK_INFO & lockinfo)
{
	lockinfo.m_Format = eL_PF_None;
	lockinfo.m_Height = 0;
	lockinfo.m_Picth  = 0;
	lockinfo.m_Pixels = NULL;
	lockinfo.m_Width  = 0;
	return NULL;
}

void  CLD3D10FileTexture::viewPort2ImageCoord(float vx , float vy , float& ix , float& iy)
{
	ix = vx;
	iy = vy;
}

void* CLD3D10FileTexture::lockRect( SURF_LOCK_INFO & lockinfo , int x , int y , int w , int h)
{
	lockinfo.m_Format = eL_PF_None;
	lockinfo.m_Height = 0;
	lockinfo.m_Picth  = 0;
	lockinfo.m_Pixels = NULL;
	lockinfo.m_Width  = 0;
	return NULL;
}

void CLD3D10FileTexture::unlock()
{

}

static int caclTexPOTSize(int w)
{
	int i = 1;
	while( i < w )
	{
		i <<= 1;
	}
	return i;
}

bool   CLD3D10FileTexture::__loadFileBuffer(const wchar_t* filename, const xint8_u* buf, int len)
{
	//if(buf)
	//{
	//	m_pFileBuffer = new char[len];
	//	memcpy(m_pFileBuffer,buf,len);
	//	m_pFileBufferLen = len;
	//	m_FileName = filename;
	//	return true;
	//}
	//else
	//{
	//	FILE* pFile = fopen(filename,"rb");
	//	if(pFile == NULL) return false;
	//	int fLen = 0;
	//	fseek(pFile,0,SEEK_END);
	//	fLen = ftell(pFile);
	//	fseek(pFile,0,SEEK_SET);
	//	m_pFileBuffer = new char[fLen];
	//	fread(m_pFileBuffer,fLen,1,pFile);
	//	fclose(pFile);	
	//	m_pFileBufferLen = fLen;
	//	m_FileName = filename;
	//	return true;
	//}
	m_FileName = filename;
	return true;
	return false;
}

bool   CLD3D10FileTexture::loadTexture(bool bLoadGopy)
{
	if( __loadDDS(bLoadGopy) )
		return true;
	if(__loadTGA(bLoadGopy))
		return true;
	return __loadTextureUseXImage(bLoadGopy);
}

bool  CLD3D10FileTexture::load(const wchar_t* filename, const xint8_u* buf, size_t len, unsigned long arg )
{
	m_texMemUsageScale = 1.0f;
	unload();
	m_pFileBufferLen = 0;

	if(__loadFileBuffer(filename,buf,len) == false)
		return false;

	m_bLoadCopy =  (arg == eLoad_SysMemCopy);
	bool bRet = loadTexture(m_bLoadCopy);

	if( bRet == false )
	{
		//m_pImage = new CX2DImage;
		//m_pImage->load(filename, m_pFileBuffer,m_pFileBufferLen);
		//CX2DImage::ImageSize _size =  m_pImage->getImageSize();
		//m_Width  = _size.m_Width;
		//m_Height = _size.m_Height;
		m_bLoadingFinish = false;
		return false;
	}
	else
	{
		m_bLoadingFinish = true ;
		return true;
	}
	//m_pImage->convertToFormat(CX2DImage::IMAGE_BGRA);
	//std::string fullName = "C:\\Users\\stanlylee\\ddd.tga";
	//m_pImage->save(fullName.c_str());


}

bool CLD3D10FileTexture::isLoaded()
{
	return m_bLoadingFinish;
}

unsigned long CLD3D10FileTexture::memUsage()
{
	return 1;
}


bool  CLD3D10FileTexture::load(const wchar_t* filename, unsigned long arg )
{
	return load(filename,NULL,0 , arg);
}

bool   CLD3D10FileTexture::__d3dxLoadTexture()
{
	HRESULT hr = S_OK;
	hr = D3DX10CreateTextureFromFile( (ID3D10Device*)m_pRenderer->getDevice(),  m_FileName.c_str(), NULL, NULL, &m_pTexture, NULL );
	if( FAILED( hr ) )
		return false;
	D3D10_RESOURCE_DIMENSION type;
	m_pTexture->GetType( &type );
	switch( type )
	{
	case D3D10_RESOURCE_DIMENSION_BUFFER:
		m_TextureType = TEX_TYPE_2D;
		break;
	case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
		m_TextureType = TEX_TYPE_1D;
		break;
	case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
		m_TextureType = TEX_TYPE_2D;
		break;
	case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
		m_TextureType = TEX_TYPE_3D;
		break;
	default:
		m_TextureType = TEX_TYPE_2D;
		break;
	}
	_createShaderResourcesImpl();
	return true;
}

bool   CLD3D10FileTexture::__loadTextureUseXImage(bool bLoadGopy)
{
	//CX2DImage::CX2DImageAutoLoker aLocker;
	//m_pImage = new CX2DImage;
	//CX2DImage* pImage = m_pImage;
	//pImage->load(m_FileName.c_str() , m_pFileBuffer,m_pFileBufferLen , CX2DImage::IMAGE_BGRA , CX2DImage::IO_LEFT_UPPER);
	//CX2DImage::ImageSize _size =  pImage->getImageSize();
	//int w  = _size.m_Width;
	//int h  = _size.m_Height;
	//m_Width  = _size.m_Width;
	//m_Height = _size.m_Height;

	//CD3DTextureWrapper texWrapper;
	//m_texMemUsageScale = 1.0f;
	//texWrapper.m_pDevice = m_pRenderer->getD3DDevice();
	//texWrapper.m_Pitch = 4 * w ;
	//texWrapper.m_Offset = 0;
	//texWrapper.m_PixelFmt = D3DFMT_A8R8G8B8;
	//texWrapper.m_nByteAlign = 4;
	//texWrapper.m_nComponent = 4;
	//texWrapper.m_initValue = 0;
	//texWrapper.setTextureSize(w , h , m_pRenderer->FitTexSize(w) , m_pRenderer->FitTexSize(h) );
	//texWrapper.__InitTexture(false,  m_pRenderer);
	//texWrapper.__uploadTexture((const char*)pImage->getImageData());
	//m_pD3DTexture = texWrapper.m_pD3DTexture;

	//texWrapper.m_pD3DTexture = NULL;
	//texWrapper.__destoryD3DTexture( m_pRenderer); 
	//__unloadImageCopy();
	return true;
}

bool CLD3D10FileTexture::__loadDDS(bool bLoadGopy)
{
	//string _ext = getFileExt( m_FileName.c_str() );
	//string file_Name = m_FileName.c_str();
	//if(_ext != "dds")
	//{
	//	return false;
	//}
	HRESULT hr = S_OK;
	if(m_pFileBufferLen != 0 && m_pFileBuffer)
	{
		return false;
	}
	else //Load From File
	{
		return __d3dxLoadTexture();
	}



	return false;
}

bool   CLD3D10FileTexture::__loadTGA(bool bLoadGopy)
{
	//std::ds_string _ext = CDirEnum::getFileExt( m_FileName.c_str() );
	//if(_ext != "tga")
	//	return false;

	//if(m_pD3DTexture)
	//{
	//	m_pRenderer->freeMem(m_pD3DTexture , m_texMemUsageScale);
	//	m_pD3DTexture->Release();
	//	m_pD3DTexture = NULL;
	//}

	//CXTgaImage tgaImage;

	//if(false == tgaImage.load(m_FileName.c_str() , (unsigned char *)m_pFileBuffer,m_pFileBufferLen) )
	//	return false;

	//int w  = tgaImage.width();
	//int h  = tgaImage.height();

	//m_Width  = tgaImage.width();
	//m_Height = tgaImage.height();

	//tgaImage.Convert2RGBA();
	//tgaImage.flipY();

	//m_texMemUsageScale = 1.0f;
	//CD3DTextureWrapper texWrapper;
	//texWrapper.m_pDevice = m_pRenderer->getD3DDevice();
	//texWrapper.m_Pitch = 4 * w ;
	//texWrapper.m_Offset = 0;
	//texWrapper.m_PixelFmt = D3DFMT_A8R8G8B8;
	//texWrapper.m_nByteAlign = 4;
	//texWrapper.m_nComponent = 4;
	//texWrapper.m_initValue = 0;
	//texWrapper.setTextureSize(w , h , m_pRenderer->FitTexSize(w) , m_pRenderer->FitTexSize(h) );
	//texWrapper.__InitTexture(false,  m_pRenderer);
	//texWrapper.__uploadTexture((const char*)tgaImage.data());
	//m_pD3DTexture = texWrapper.m_pD3DTexture;

	//texWrapper.m_pD3DTexture = NULL;
	//texWrapper.__destoryD3DTexture(  m_pRenderer);
	//m_bLoadingFinish = true;

	//if(m_bLoadCopy)
	//{
	//	m_pImage = new CX2DImage;
	//	m_pImage->setImageData( (const char *)tgaImage.data(),w , h , XGUI::CX2DImage::IMAGE_BGRA);
	//}


	return false;
}

void   CLD3D10FileTexture::__uploadTexture()
{
	if(m_bLoadingFinish )
		return ;
	m_bLoadingFinish = true;
	if(m_pFileBuffer == NULL) return ;
	//Release previous texture
	if(m_pShaderResourceView)
	{
		m_pRenderer->freeMem(m_pShaderResourceView , m_texMemUsageScale);
		m_pShaderResourceView->Release();
		m_pShaderResourceView = NULL;
	}
	loadTexture(m_bLoadCopy);
	if(m_pShaderResourceView == NULL)
	{
		return ;
	}
}



int    CLD3D10FileTexture::getResSize()
{
	return 4 * m_Height * m_Width;
}

bool CLD3D10FileTexture::onDeviceLost(bool bDeviceChange)
{
	if(1)//bDeviceChange)
	{
		__unloadImageCopy();
		__unloadTexObject();
		m_bLoadingFinish = false;
	}

	return true;//unload();
}

void  CLD3D10FileTexture::__unloadImageCopy()
{
	//if( m_pImage )
	//{
	//	m_pImage->free();
	//	delete m_pImage;
	//	m_pImage = NULL;
	//}
}

void  CLD3D10FileTexture::__unloadFileBuffer()
{
	if(m_pFileBuffer != NULL) 
	{
		delete [] m_pFileBuffer;
		m_pFileBuffer = 0;
		m_pFileBufferLen = 0;
	}
}

void CLD3D10FileTexture::__unloadTexObject()
{
	if(m_pShaderResourceView)
	{
		m_pRenderer->freeMem(m_pShaderResourceView , m_texMemUsageScale);
		m_pShaderResourceView->Release();
		m_pShaderResourceView = NULL;
	}
	m_bLoadingFinish = false;
}

bool   CLD3D10FileTexture::unload()
{
	__unloadFileBuffer();
	__unloadImageCopy();
	__unloadTexObject();
	m_bLoadingFinish = false;
	return true;
}


bool CLD3D10FileTexture::validate()
{
	__uploadTexture();
	return m_pShaderResourceView != NULL;
}


void CLD3D10FileTexture::_create1DTexture()
{

}


void CLD3D10FileTexture::_create2DTexture()
{

	D3D10_TEXTURE2D_DESC desc;
	m_p2DTex = (ID3D10Texture2D*)m_pTexture;
	m_p2DTex->GetDesc( &desc );

	int i = 0;
	m_srvDesc.Format                    = desc.Format;
	m_srvDesc.ViewDimension             = D3D10_SRV_DIMENSION_TEXTURE2D;
	m_srvDesc.Texture2D.MostDetailedMip = 0;
	m_srvDesc.Texture2D.MipLevels       = desc.MipLevels;

	m_Width     = desc.Width;
	m_Height    = desc.Height;
	m_TexHeight = m_Height;
	m_TexWidth  = m_Width;
	

	HRESULT hr = S_OK;
	hr = ((ID3D10Device*)m_pRenderer->getDevice())->CreateShaderResourceView( m_pTexture, &m_srvDesc, &m_pShaderResourceView );
	//hr = g_pd3dDevice->CreateShaderResourceView( pTexture, NULL, &g_pTextureRV );

	if( FAILED( hr ) )
		return;
}


void CLD3D10FileTexture::_create3DTexture()
{

}


void CLD3D10FileTexture::_createShaderResourcesImpl(void)
{
	// load based on tex.type
	switch (this->getTextureType())
	{
	case TEX_TYPE_1D:
		this->_create1DTexture();
		break;
	case TEX_TYPE_2D:
	case TEX_TYPE_CUBE_MAP:
		this->_create2DTexture();
		break;
	case TEX_TYPE_3D:
		this->_create3DTexture();
		break;
	default:
		break;
	}
}

NAMESPACE_LABOR3D_END